Since USER_PTRS_PER_PGD depends on TASK_SIZE and thus on the current
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 7 Feb 2006 18:16:11 +0000 (19:16 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 7 Feb 2006 18:16:11 +0000 (19:16 +0100)
thread, it must not be used in code that can be called in the context
switch path (otherwise the 32-bitness of the outgoing task is used
here rather then the 32-bitness of the incoming one, possibly
resulting in large parts of the page tables not getting converted to
read-only).

Signed-off-by: Jan Beulich <JBeulich@novell.com>
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c

index dacbeb23ee4122eb046676e65fce44c72b453dc9..a39d4ab23ca39ba96f19ef916f91b58b0655f7c3 100644 (file)
@@ -40,7 +40,14 @@ static void mm_walk(struct mm_struct *mm, pgprot_t flags)
        int          g,u,m;
 
        pgd = mm->pgd;
-       for (g = 0; g <= USER_PTRS_PER_PGD; g++, pgd++) {
+       /*
+        * Cannot iterate up to USER_PTRS_PER_PGD as these pagetables may not
+        * be the 'current' task's pagetables (e.g., current may be 32-bit,
+        * but the pagetables may be for a 64-bit task).
+        * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
+        * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
+        */
+       for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
                if (pgd_none(*pgd))
                        continue;
                pud = pud_offset(pgd, 0);